import utils from '../utils'
import ShapeFile from '../shapefile'

function DataTable(obj) {
  let records = null
  if (utils.isArray(obj)) {
    records = obj
  } else {
    records = []
    if (utils.isInteger(obj)) {
      for (let i = 0; i < obj; i += 1) {
        records.push({})
      }
    } else if (obj) {
      utils.error(`Invalid DataTable constructor argument:${obj}`)
    }
  }
  this.exportAsDbf = function(opts) {
    return ShapeFile.exportRecords(records, opts.encoding, opts.field_order)
  }
  this.getRecords = function() {
    return records
  }
  this.getReadOnlyRecordAt = function(i) {
    return utils.copyRecord(records[i]) // deep-copies plain objects but not other constructed objects
  }
}
const dataTableProto = {
  fieldExists: function(name) {
    return utils.contains(this.getFields(), name)
  },
  toString: function() {return JSON.stringify(this)},
  toJSON: function() {
    return this.getRecords()
  },
  addField: function(name, init) {
    const useFunction = utils.isFunction(init)
    if (!utils.isNumber(init) && !utils.isString(init) && !useFunction) {
      utils.error("DataTable#addField() requires a string, number or function for initialization")
    }
    if (this.fieldExists(name)) utils.error("DataTable#addField() tried to add a field that already exists:", name)
    // var dataFieldRxp = /^[a-zA-Z_][a-zA-Z_0-9]*$/;
    // if (!dataFieldRxp.test(name)) error("DataTable#addField() invalid field name:", name);

    this.getRecords().forEach(function(obj, i) {
      obj[name] = useFunction ? init(obj, i) : init
    })
  },
  getRecordAt: function(i) {
    return this.getRecords()[i]
  },
  addIdField: function() {
    this.addField('FID', function(obj, i) {
      return i
    })
  },
  deleteField: function(f) {
    this.getRecords().forEach(function(o) {
      delete o[f]
    })
  },
  getFields: function() {
    return utils.findFieldNames(this.getRecords())
  },
  update: function(f) {
    const records = this.getRecords()
    for (let i = 0, n = records.length; i < n; i += 1) {
      records[i] = f(records[i], i)
    }
  },
  clone: function() {
    // TODO: this could be sped up using a record constructor function
    // (see getRecordConstructor() in DbfReader)
    const records2 = this.getRecords().map(internal.copyRecord)
    return new DataTable(records2)
  },
  size: function() {
    return this.getRecords().length
  }
}

extend(DataTable.prototype, dataTableProto)
function extend(o) {
  const dest = o || {}
  const n = arguments.length
  for (let i = 1; i < n; i += 1) {
    let src = arguments[i] || {}
    for (let key in src) {
      if (src.hasOwnProperty(key)) {
        dest[key] = src[key]
      }
    }
  }
  return dest
}
export {
  DataTable,
  dataTableProto,
}
export default {}
